package com.huonan.component.algorithm;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 多个线程处理多个任务，
 * 要求：
 * 1. 一个线程同时只能处理一个任务
 * 2. 一个任务未执行完成，下次定时任务不能执行
 */
@Component
@Slf4j
public class DirectoryScanner {
    private static ExecutorService executorService;
    private Semaphore semaphore;
    private Map<String, Boolean> directoryStatus;
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    public DirectoryScanner() {
        int numThreads = 5;
//        executorService = ExecutorPool.getExecutorService(numThreads);
        executorService = ThreadUtil.newExecutor(numThreads, numThreads, 100);
        semaphore = new Semaphore(numThreads);
        directoryStatus = new HashMap<>();
    }

    //    @Scheduled(fixedDelay = 5000) // 每隔5秒执行一次任务
    public void scanDirectories() {
        String[] directories = {"/Users/lxp/t_dir/t01", "/Users/lxp/t_dir/t02", "/Users/lxp/t_dir/t03"};
        for (String directory : directories) {
            // 标记当前目录为不可执行状态，直到任务执行完成
            Boolean aBoolean;
            aBoolean = readLock(directory);
            if (aBoolean == null || aBoolean) {
                writeLock(directory);
                executorService.execute(() -> {
                    try {
                        log.info("{}: start {}", directory, Thread.currentThread().getName());
                        try {
                            Thread.sleep(RandomUtil.randomInt(1, 5) * 100L);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        // semaphore.acquire();
                        processDirectory(directory);
                    } finally {
                    }
                });
            }
        }
    }

    private void writeLock(String directory) {
        lock.writeLock().lock();
        try {
            directoryStatus.put(directory, false);
        } finally {
            lock.writeLock().unlock();
        }
    }

    private Boolean readLock(String directory) {
        Boolean aBoolean;
        lock.readLock().lock();
        try {
            aBoolean = directoryStatus.get(directory);
        } finally {
            lock.readLock().unlock();
        }
        return aBoolean;
    }

    private void processDirectory(String directory) {

        // 处理目录逻辑，异步执行
        File dir = new File(directory);
        log.info("{}: process {}", directory, Thread.currentThread().getName());

        // 在任务执行完成后，将目录状态恢复为可执行状态
        directoryStatus.put(directory, true);
        log.info("{}: end {}", directory, Thread.currentThread().getName());

    }

    public static void main(String[] args) throws InterruptedException {
        DirectoryScanner directoryScanner = new DirectoryScanner();
        for (int i = 0; i < 10; i++) {
            directoryScanner.scanDirectories();
            ThreadUtil.safeSleep(100);
//            for (Thread thread : ThreadUtil.getThreads()) {
//                log.info("{} 状态：{}",thread.getName(),thread.getState());
//            }
        }

        executorService.shutdown();
        if (executorService.isTerminated()) {
            Thread.yield();
        }
    }
}